package cn.exrick.manager.service.hotclassload;

import org.apache.commons.lang3.StringUtils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestOutOfMemoryExample {

    private volatile static boolean running = true;

    private static ExecutorService executors = Executors.newFixedThreadPool(20);
    public static void main(String[] args) throws Exception {
        MyThread myThread = new MyThread();
        try {
            executors.submit(myThread);
            /*for(int i = 0;i< 20;i++){
            }*/
            System.out.println("press any key to stop. ");
            System.in.read();

        } finally {
            running = false;
            executors.shutdown();
        }
    }

    private final static class MyThread implements Runnable {
        @Override
        public void run() {
            while (running) {
                try {
                    loadClass();

                } catch (Throwable se) {
                    se.printStackTrace();

                }
                try {
                    Thread.sleep(100);
                } catch (Exception se) {
                    System.out.println("Caught InterruptedException, shutting down.");
                    running = false;
                }
            }
        }
    }

    private static void loadClass() throws Exception {
        ClassLoader classLoader = new MyClassLoader();
        Class<?> c = Class.forName(ThreadLoadInClass.class.getName(), true, classLoader);
        c.newInstance();
    }

    private final static class MyClassLoader extends ClassLoader {

        public MyClassLoader() {
            super(MyClassLoader.class.getClassLoader());
        }

        @Override
        public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
            if (!ThreadLoadInClass.class.getName().equals(name)) {
                return super.loadClass(name, resolve);
            }
            try(FileInputStream fileInputStream = new FileInputStream(new File("C:\\work\\hilife\\hilife-decoration\\hilife-decoration-provider\\target\\test-classes\\"+ StringUtils.replace(ThreadLoadInClass.class.getName(),".","\\")+".class"));
                ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
                /*Path path = Paths.get(ThreadLoadInClass.class.getName()
                        + ".class");*/

                int b = 0;
                while((b =fileInputStream.read()) != -1){
                    bos.write(b);
                }
                byte[] d = bos.toByteArray();
               // byte[] classBytes = Files.readAllBytes(path);
                Class<?> c = defineClass(name, d, 0, d.length);
                if (resolve) {
                    resolveClass(c);
                }
                return c;
            } catch (IOException ex) {
                throw new ClassNotFoundException("Could not load " + name, ex);
            }
        }

    }

     public final static class ThreadLoadInClass {
         final static byte[] d = new byte[1024 * 1024 * 100];
        private final static ThreadLocal<ThreadLoadInClass> threadLocal = new ThreadLocal();

        public ThreadLoadInClass() {
            threadLocal.set(this);
        }


    }
}
